/*----------------------------------------------------------------------------
Owner(s): Shane Whitfield
$Copyright: $
$Id: $
----------------------------------------------------------------------------*/

#include "touchmgr.h"
#include "camera.h"
#include "timermgr.h"

/*--------------------------------------------------------------------------*/

#define LOG_TOUCH_EVENTS 0

/*--------------------------------------------------------------------------*/

CTouchMgr::CTouchMgr(): super("CTouchMgr")
{
	m_tContactStarted = 0.0f;
	m_state = EState_NoTouch;
	clearTouchEvents();
	clearTouchPos();
}

void CTouchMgr::clearTouchEvents()
{
	memset(m_pendingHasFrameTouchEvent, 0, sizeof(bool) * ETouchType_Count);
}

void CTouchMgr::clearTouchPos()
{
	memset(m_pendingTouchEventScreenPos, 0, sizeof(Vector2f) * ETouchType_Count);
	memset(m_pendingTouchEventScreenPos2, 0, sizeof(Vector2f) * ETouchType_Count);
}

void CTouchMgr::pendingToCurrent()
{	
	memcpy(m_hasFrameTouchEvent, m_pendingHasFrameTouchEvent, sizeof(bool) * ETouchType_Count);
	memcpy(m_touchEventScreenPos, m_pendingTouchEventScreenPos, sizeof(Vector2f) * ETouchType_Count);
	memcpy(m_touchEventScreenPos2, m_pendingTouchEventScreenPos2, sizeof(Vector2f) * ETouchType_Count);	
	memset(m_pendingHasFrameTouchEvent, 0, sizeof(bool) * ETouchType_Count);
	
	//update the state?
	for (int iEvent = 0; iEvent < ETouchType_Count; ++iEvent)
	{
		if (m_hasFrameTouchEvent[iEvent])
		{
			switch(iEvent)
			{
			case ETouchType_SingleTouchStart:	//fall-through
			case ETouchType_DoubleTapStart:	
				{
					setState(EState_TouchStart);
				}
				break;
			case ETouchType_SingleTouchMoved:
				{
					setState(EState_Touching);
				}
				break;
			case ETouchType_SingleTouchEnd:
				{
					setState(EState_TouchingEnding);
				}
				break;
			case ETouchType_TouchCancelled:
				{
					setState(EState_TouchingEnding);
				}
				break;
			}
		}
	}
	
#if DEBUG && LOG_TOUCH_EVENTS
	bool hasEvent = false;
	for (int iEvent = 0; iEvent < KGameTouchCount; ++iEvent)
	{
		if(HasTouchEvent((ETouchType)iEvent, false))
		{
			hasEvent = true;
			break;
		}
	}
	
	if (hasEvent)
	{
		printf("Touches:");
		for (int iEvent = 0; iEvent < KGameTouchCount; ++iEvent)
		{
			if (HasTouchEvent((ETouchType)iEvent, false))
			{
				switch(iEvent)
				{
				case ETouchType_SingleTouchStart:
					{
						printf(" begin(w%g, w%g)", GetTouchEventWorldPos(ETouchType_SingleTouchStart).x, GetTouchEventWorldPos(ETouchType_SingleTouchStart).y);
					}
					break;
				case ETouchType_DoubleTapStart:	
					{
						printf(" 2xbegin(w%g, w%g)", GetTouchEventWorldPos(ETouchType_DoubleTapStart).x, GetTouchEventWorldPos(ETouchType_DoubleTapStart).y);
					}
					break;
				case ETouchType_SingleTouchMoved:
					{
						printf(" moved(w%g, w%g)", GetTouchEventWorldPos(ETouchType_SingleTouchMoved).x, GetTouchEventWorldPos(ETouchType_SingleTouchMoved).y);
					}
					break;
				case ETouchType_SingleTouchEnd:
					{
						printf(" end(w%g, w%g)", GetTouchEventWorldPos(ETouchType_SingleTouchEnd).x, GetTouchEventWorldPos(ETouchType_SingleTouchEnd).y);
					}
					break;
				case ETouchType_TouchCancelled:
					{
						printf(" cancelled(w%g, w%g)", GetTouchEventWorldPos(ETouchType_SingleTouchEnd).x, GetTouchEventWorldPos(ETouchType_SingleTouchEnd).y);
					}
					break;
				case ETouchType_DoubleTouchStart:
					{
						printf(" 2xbegin 1(s%g, s%g) 2 (s%g, s%g)", GetTouchEventScreenPos(ETouchType_DoubleTouchStart).x, GetTouchEventScreenPos(ETouchType_DoubleTouchStart).y, 
																	GetTouchEventScreenPos2(ETouchType_DoubleTouchStart).x, GetTouchEventScreenPos2(ETouchType_DoubleTouchStart).x);
					}
					break;
				case ETouchType_DoubleTouchMoving:
					{
						printf(" 2xmoving 1(s%g, s%g) 2(s%g, s%g)", GetTouchEventScreenPos(ETouchType_DoubleTouchMoving).x, GetTouchEventScreenPos(ETouchType_DoubleTouchMoving).y,
																	GetTouchEventScreenPos2(ETouchType_DoubleTouchMoving).x, GetTouchEventScreenPos2(ETouchType_DoubleTouchMoving).y);
					}
					break;
				}
			}
		}
		
		printf("\n");
	}
#endif //DEBUG && LOG_TOUCH_EVENTS
}

void CTouchMgr::setState(EState i_state)
{
	m_state = i_state;
	
	switch(m_state)
	{
	case EState_TouchStart:
		{
			m_tContactStarted = T();
		}
		break;
	}
}

float CTouchMgr::GetContactDuration() const
{
	if (m_state == EState_NoTouch)
	{
		return 0.0f;
	}
	
	return T() - m_tContactStarted;
}

void CTouchMgr::OnPreWorldUpdate()
{
	pendingToCurrent();
}

void CTouchMgr::OnPostWorldLoad()
{
	m_state = EState_NoTouch;
	clearTouchPos();
}

void CTouchMgr::OnPreIntroUpdate()
{
	pendingToCurrent();
}

void CTouchMgr::OnPreMapUpdate()
{
	pendingToCurrent();
}

void CTouchMgr::OnPostWorldUpdate()
{
	update();
}

void CTouchMgr::OnPostIntroUpdate()
{
	update();
}

void CTouchMgr::OnPostMapUpdate()
{
	update();
}

void CTouchMgr::update()
{
	switch(m_state)
	{
	case EState_TouchStart:
		{
			setState(EState_Touching);
		}
		break;
	case EState_TouchingEnding:
		{
			setState(EState_NoTouch);
		}
		break;
	}
}

void CTouchMgr::RegisterPendingTouch(ETouchType i_touchType, const Vector2f& i_screenPos, int i_numTaps, Vector2f* i_screenPos2)
{
	m_pendingHasFrameTouchEvent[i_touchType] = true;
	m_pendingTouchEventScreenPos[i_touchType] = i_screenPos;
	
	if (i_screenPos2)
	{
		m_pendingTouchEventScreenPos2[i_touchType] = *i_screenPos2;
	}
}

Vector2f CTouchMgr::GetTouchEventWorldPos(ETouchType i_touchType) const
{
	Vector2f cameraSpace = g_camera.ScreenToCameraSpace(m_touchEventScreenPos[i_touchType]);
	return cameraSpace + g_camera.GetPos();
}

Vector2f CTouchMgr::GetTouchEventWorldPos2(ETouchType i_touchType) const
{
	Vector2f cameraSpace = g_camera.ScreenToCameraSpace(m_touchEventScreenPos2[i_touchType]);
	return cameraSpace + g_camera.GetPos();
}

bool CTouchMgr::HasTouchEvent(ETouchType i_touchType, bool shouldAbsorb) const
{
	bool isOn = m_hasFrameTouchEvent[i_touchType];
	if (shouldAbsorb)
	{
		m_hasFrameTouchEvent[i_touchType] = false;
	}
	
	return isOn;
}

/*-----------------------------------EOF!-----------------------------------*/ 